<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      /**
       * 数值的扩展
       */
      // 二进制与八进制表示法
      // 二进制 0b
      console.log(0b111110111);
      // 八进制 0o
      console.log(0o767);

      // Number.isFinite()  ,Number.isNaN()
      // Number.isFinite() 用来检查一个数是否为有限的
      let { log } = console;
      log(Number.isFinite(15));
      log(Number.isFinite(0.8));
      log(Number.isFinite(NaN));
      log(Number.isFinite(Infinity));
      log(Number.isFinite(-Infinity));
      log(Number.isFinite("foo"));
      log(Number.isFinite("15"));
      // Number.isNaN() 用来检查一个值是否为NaN
      log(Number.isNaN(NaN));
      log(Number.isNaN(17));
      log(Number.isNaN("14"));
      log(Number.isNaN(true));
      log(Number.isNaN(9 / NaN));
      log(Number.isNaN("true" / 0));
      log(Number.isNaN("true" / "true"));

      // Number.parseInt()  Number.parseFFloat()
      log(parseInt("12.34"));
      log(parseFloat("123.45#"));

      log(Number.parseInt("12.34"));
      log(Number.parseFloat("123.45#"));

      // Number.isInteger() 用来判断一个数值是否为整数
      log(Number.isInteger(25));
      log(Number.isInteger(25.1));

      /**
       * Math 扩展
       */
      //  Math.trunc() 去除一个数的小数部分
      log("Math-----------------------------");
      log(Math.trunc(4.1));
      log(Math.trunc(4.9));
      log(Math.trunc(-4.9));
      log(Math.trunc(-4.1));
      log(Math.trunc(-0.12346));
      log(Math.trunc(true));
      log(Math.trunc(false));
      log(Math.trunc(null));
      log(Math.trunc(NaN));
      log(Math.trunc("foo"));
      log(Math.trunc());
      log(Math.trunc(undefined));

      // Math.sign() 用来判断一个数是正数，负数，还是零
      // 参数为正数，返回+1；
      // 参数为负数，返回-1；
      // 参数为 0，返回0；
      // 参数为-0，返回-0;
      // 其他值，返回NaN。
      log(Math.sign(-5));
      log(Math.sign(5));
      log(Math.sign(0));
      log(Math.sign(-0));
      log(Math.sign(NaN));
      log(Math.sign());
      log(Math.sign(true));
      log(Math.sign(false));
      log(Math.sign(null));
      log(Math.sign("9"));
      log(Math.sign("foo"));
      log(Math.sign(""));
      log(Math.sign(undefined));

      // Math.cbrt() 用于计算一个数的立方根
      log(Math.cbrt(9));
      log(Math.cbrt(-1));
      log(Math.cbrt(1));
      log(Math.cbrt(2));
      log(Math.cbrt("8"));
      log(Math.cbrt("Hello"));

      // Math.clz32() 返回数值32位形式下有多少个前导0
      log(Math.clz32(0));
      log(Math.clz32(1));
      log(Math.clz32(1000));
      log(Math.clz32(1 << 1));
      log(Math.clz32(1 << 2));
      log(Math.clz32(1 << 29));
      log(Math.clz32(3.2)); //只考虑整部分
      log(Math.clz32());
      log(Math.clz32(NaN));
      log(Math.clz32(Infinity));
      log(Math.clz32(null));
      log(Math.clz32("foo"));
      log(Math.clz32([]));
      log(Math.clz32({}));
      log(Math.clz32(true));

      //Math.imul() 返回两个数以32位带符号形式相乘的结果
      log(Math.imul(2, 4));
      log(Math.imul(-1, 8));
      log(Math.imul(-2, -2));

      // Math.fround() 返回一个数的32位单精度浮点数形式
      log(Math.fround(0));
      log(Math.fround(1));
      log(Math.fround(2 ** 24 - 1));

      /**
       * 函数的扩展
       */
      // 函数参数的默认值
      function fun(x, y = "world") {
        console.log(x, y);
      }
      fun("Hello");
      fun("Hello", "China");

      function Point(x = 0, y = 0) {
        this.x = 0;
        this.y = 0;
      }
      const p = new Point();
      log(p);

      // 与解构赋值的默认值相结合
      function foo({ x, y = 5 }) {
        console.log(x, y);
      }

      foo({});
      foo({ x: 1 });
      foo({ x: 1, y: 2 });
      // foo()

      function foo1({ x, y = 5 } = {}) {
        console.log(x, y);
      }

      foo1();

      function fetch(url, { body = "", method = "GET", headers = {} }) {
        console.log(method);
      }

      fetch("http://example.com", {});
      // fetch("http://example.com")  要报错

      function fetch1(url, { body = "", method = "GET", headers = {} } = {}) {
        console.log(method);
      }
      fetch1("http://example.com");

      function m1({ x = 0, y = 0 } = {}) {
        return [x, y];
      }
      function m2({ x, y } = { x: 0, y: 0 }) {
        return [x, y];
      }

      log(m1());
      log(m2())

      log(m1({ x: 3, y: 8 }))
      log(m2({ x: 3, y: 8 }))

      log(m1({ x: 3 }))
      log(m2({ x: 3 }))
      log(m1({}))
      log(m2({}))

      log(m1({ z: 1 }))
      log(m2({ z: 1 }))

      // 默认参数的位置  
      // 函数参数设置默认值时，若非尾部的参数设置默认值，则这个参数无法省略的
      function fu(x=1,y){
        return [x,y]
      }
      log(fu())
      log(fu(2))
      // log(fu(,1)) 报错
      log(fu(undefined,1))


      function fu2(x,y=5,z){
        return [x,y,z]
      }
      log(fu2())
      log(fu2(1))
      // log(fu2(1,,2)) 报错
      log(fu2(1,undefined,2))

      /**
       * length属性
       * 返回函数参数的个数
       * 在指定了默认值后，length属性将失真
      */
      log(function(a){}.length)
      log(function(a=5){}.length)
      log(function(a,b,c=1){}.length)

      // 作用域
      var g = 1;
      function f3(g,y=g){
        console.log(y)
      }
      f3(2)
 
      let foa = "outer"
      function bar (func = () => foa){
        let foa = "inner";
        console.log(func())
      }
      bar()

      // -----------复杂示例
      log(">>>>>>>>>>>>>>>")
      var aa = 1
      function fob (aa,y = function(){aa =2}){
        var aa = 3
        console.log(window.aa) //1
        y()
        console.log(window.aa) //1
        console.log(aa) //3
      }
      fob()
      log(aa) //1

      log(">>>>>>>>>>>>>>>>>")
      var bb = 7
      function foe(bb, y1= function(){ bb =4 }){
        bb = 3
        y1()
        console.log(bb)
      }

      foe ()
      log(bb)

      /**
       * 利用参数默认值，可以指定某个参数不可以省略，若省略就抛出一个错误
      */

      function throwIfMissing(){
        throw new Error("Missing parameter")
      }

      function foo4(mustBeProvided = throwIfMissing()){
        return mustBeProvided
      }
      // foo4() 报错
      foo4(2)








    </script>
  </body>
</html>
